<template>
  <div
    class="outreach-box"
    :class="treeStore.isShowStrategyDetail ? 'not-click' : ''"
    v-if="!showLinux"
  >
    <el-form
      class="form-seach"
      ref="outreachFormRef"
      :rules="rules"
      label-width="100"
      :model="outreachDataObj"
    >
      <HETForm :formConfig="formConfig"></HETForm>

      <el-form-item label="探测协议" v-if="outreachDataObj.intranet">
        <el-radio-group v-model="outreachDataObj.intranetset" @change="radioClick">
          <el-radio key="TCP" value="TCP">{{ "TCP" }}</el-radio>
          <el-radio key="HTTP" value="HTTP">{{ "HTTP" }}</el-radio>
          <el-radio key="lCMP" value="lCMP">{{ "lCMP" }}</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="IP地址" prop="ip" v-if="outreachDataObj.intranet">
        <el-input
          v-model="outreachDataObj.ip"
          style="width: 300px"
          placeholder="请填写正确的内网探测IP地址"
        />
      </el-form-item>
      <el-form-item
        label="端口"
        prop="port"
        v-if="outreachDataObj.intranet && outreachDataObj.intranetset != 'lCMP'"
      >
        <el-input
          v-model="outreachDataObj.port"
          style="width: 300px"
          placeholder="请填写正确的内网探测端口:0-65535"
        />
      </el-form-item>
      <el-form-item label="探测周期" prop="time">
        <el-input
          v-model.number="outreachDataObj.time"
          style="width: 300px"
          placeholder="请填写正确的探测周期:10分钟-1440分钟"
        /><span class="ml-2.5">分钟探测一次</span>
      </el-form-item>
      <el-form-item v-if="!treeStore.isShowStrategyDetail">
        <el-button type="primary" @click="setOutreach('')">确定</el-button>
        <el-button @click="clear('')">清空</el-button>
      </el-form-item>
    </el-form>
  </div>
  <div
    class="mt-10"
    :class="treeStore.isShowStrategyDetail ? 'not-click' : ''"
    v-if="showLinux"
  >
    <HETTable
      ref="netDetectionTable"
      :pageSize="10"
      :tableFields="netDetectionTableFields"
      :tableData="netDetectionTableData"
      :enableSearch="false"
      :tableCheckbox="true"
      :operationCol="treeStore.isShowStrategyDetail ? [] : operationCol"
      :headerOperation="treeStore.isShowStrategyDetail ? [] : headerOperation"
      :total="netDetectionTotal"
      @getTableData="getNetDetectionData"
    >
    </HETTable>
  </div>
  <el-dialog
    v-model="netDetectionDialogVModel"
    title="非法外联"
    width="600"
    :center="true"
    :close-on-click-modal="false"
  >
    <el-form
      :model="netDetectionForm"
      ref="netDetectionFormRef"
      label-width="auto"
      class="margin-auto"
      :rules="netDetectionRules"
      style="max-width: 350px"
    >
      <el-form-item label="规则名称" prop="name">
        <el-input
          v-model="netDetectionForm.name"
          style="width: 240px"
          type="text"
          autocomplete="off"
        />
      </el-form-item>
      <el-form-item label="通信协议" prop="protocal">
        <el-radio-group
          v-model.number="netDetectionForm.protocal"
          @change="changeProtocal"
        >
          <el-radio :value="1">TCP</el-radio>
          <el-radio :value="3">ICMP</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="目的地址" prop="remoteAddr">
        <el-input
          v-model="netDetectionForm.remoteAddr"
          style="width: 240px"
          type="text"
          autocomplete="off"
        />
      </el-form-item>
      <el-form-item label="目的端口" prop="remotePort">
        <el-input
          v-model.number="netDetectionForm.remotePort"
          style="width: 240px"
          type="text"
          autocomplete="off"
          :disabled="disableRemotePort"
        />
      </el-form-item>
      <el-form-item label="是否启用" prop="enable">
        <el-switch v-model="netDetectionForm.enable" class="switch-color" />
      </el-form-item>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="submitFn"> 确认 </el-button>
        <el-button @click="netDetectionDialogVModel = false">取消</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup>
import { ref, reactive, toRefs, onMounted, watch, toRaw, nextTick } from "vue";
import { Delete, Plus } from "@element-plus/icons-vue";
import {
  req_getOutreach,
  req_setOutreach,
  req_getNetDetectionRules,
  req_addNetDetectionRules,
  req_updateNetDetectionRules,
  req_deleteNetDetectionRules,
} from "~/utils/axios/setting.js";
import { useTreeStore } from "~/utils/pinia/tree.js";
import HETForm from "~/components/common/HETForm.vue";
import { validIp, validPort } from "~/utils/common/validation.js";
import { eventBus } from "~/utils/common/eventBus.js";
import { ElMessage } from "element-plus";
let initData = null;
eventBus.on("getStrategyDetail", (detail) => {
  treeStore.openTreeFlag = false;
  if (treeStore.osType == "win") {
    setOutreachDataObj(detail.data[0].net_detect);
  } else {
    showLinux.value = true;
    let typeStr = "";
    netDetectionTableData.value = detail.data.map((item) => {
      switch (item.protocal) {
        case 1:
          typeStr = "TCP";
          break;
        case 3:
          typeStr = "ICMP";
          break;
      }
      return {
        ...item,
        enable: Boolean(item.enable),
        protocal: typeStr,
      };
    });
    netDetectionTotal.value = Number(detail.total) || 0;
  }
});
let treeStore = useTreeStore();
treeStore.openTree();
// 请求及设置参数
const getParams = ["net_detect"];
// 表单数据
const outreachDataObj = reactive({
  internet: false,
  intranet: false,
  intranetset: "",
  ip: "",
  port: "",
  time: "",
});
// port验证
const portValidator = (rule, value, callback) => {
  let thisValue = Number(value);
  if (thisValue >= 10 && thisValue <= 1440) {
    callback();
  } else {
    callback(new Error("输入的探测周期不合法"));
  }
};
// form表单ref
const outreachFormRef = ref();
const outreachDatas = toRefs(outreachDataObj);
const rules = reactive({
  ip: [
    { required: true, message: "请输入正确的IP", trigger: "change" },
    { validator: validIp, trigger: "change" },
  ],
  port: [
    {
      required: true,
      message: "请填写正确的内网探测端口:0-65535",
      trigger: "change",
    },
    { validator: validPort, trigger: "change" },
  ],
  time: [
    {
      required: true,
      message: "请填写正确的探测周期:10-1440",
      trigger: "change",
    },
    { validator: portValidator, trigger: "change" },
  ],
});
// 表单中各表单元素的设置
const formConfig = reactive([
  {
    prop: "internet",
    type: "switch",
    model: outreachDatas.internet,
    label: "互联网探测",
    tip: "注:只可用于互联网检测并告警",
  },
  {
    prop: "intranet",
    type: "switch",
    model: outreachDatas.intranet,
    label: "内网探测",
    tip: "注:可用于检查内网限制连接网段并告警",
  },
]);
const disableRemotePort = ref(false);
const changeProtocal = (val) => {
  if (val == 3) {
    disableRemotePort.value = true;
    netDetectionRules.remotePort = [];
    netDetectionForm.remotePort = "";
  } else {
    disableRemotePort.value = false;
    netDetectionRules.remotePort = [
      {
        required: true,
        message: "请填写正确的内网探测端口:0-65535",
        trigger: "blur",
      },
      { validator: validPort, trigger: "blur" },
    ];
  }
};
const radioClick = (obj) => {
  if (obj == initData.protocol) {
    outreachDataObj.ip = initData.ip;
    outreachDataObj.port = initData.port;
  } else {
    clear();
  }
};
const setOutreach = () => {
  if (!outreachFormRef || !treeStore.treeDeviceId) return;
  outreachFormRef.value.validate(async (valid, fields) => {
    if (valid || !outreachDataObj.intranet) {
      let obj = {
        internet: Number(outreachDataObj.internet),
        intranet: Number(outreachDataObj.intranet),
        intranetset: {
          protocol: outreachDataObj.intranetset,
          ip: outreachDataObj.ip,
          port: Number(outreachDataObj.port),
        },
        time: Number(outreachDataObj.time),
      };
      let net_detect = [
        {
          key: "net_detect",
          value: JSON.stringify(obj),
        },
      ];
      // let getParams = JSON.stringify(net_detect)
      req_setOutreach(treeStore.treeDeviceId, JSON.stringify(net_detect)).then((res) => {
        if (res.data.succeed) {
          ElMessage({
            message: "设置成功",
            type: "success",
          });
        }
      });
    }
  });
};
const clear = () => {
  outreachDataObj.ip = outreachDataObj.port = "";
};
const setOutreachDataObj = (data) => {
  data = JSON.parse(data);
  outreachDataObj.internet = Boolean(data.internet);
  outreachDataObj.intranet = Boolean(data.intranet);
  outreachDataObj.intranetset = data.intranetset.protocol;
  outreachDataObj.ip = data.intranetset.ip;
  outreachDataObj.port = data.intranetset.port;
  outreachDataObj.time = data.time;
};
// linux系统页面展示
const showLinux = ref(false);
const netDetectionTable = ref();
const netDetectionTableData = ref();
const netDetectionTotal = ref(0);
const netDetectionFormRef = ref();
// 弹出框表单校验
const netDetectionRules = reactive({
  name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
  protocal: [{ required: true, message: "协议不能为空", trigger: "blur" }],
  remoteAddr: [
    { required: true, message: "请输入正确的IP", trigger: "blur" },
    { validator: validIp, trigger: "blur" },
  ],
  remotePort: [
    {
      required: true,
      message: "请填写正确的内网探测端口:0-65535",
      trigger: "blur",
    },
    { validator: validPort, trigger: "blur" },
  ],
});
const netDetectionEditSubmit = (row) => {
  netDetectionFormRef.value.validate((valid, fields) => {
    if (valid) {
      let deployParam = {
        name: row.name,
        protocal: row.protocal,
        remoteAddr: row.remoteAddr,
        remotePort: Number(row.remotePort),
        id: row.id,
        enable: Number(row.enable),
      };
      if (row.id) {
        req_updateNetDetectionRules(treeStore.treeDeviceId, deployParam).then((res) => {
          ElMessage({
            message: "设置成功",
            type: "success",
          });
        });
      } else {
        req_addNetDetectionRules(treeStore.treeDeviceId, deployParam).then((res) => {
          ElMessage({
            message: "新增成功",
            type: "success",
          });
        });
      }
      netDetectionDialogVModel.value = false;
      netDetectionTable.value.getTableData();
    }
  });
};

const netDetectionEditSubmit2 = (row) => {
  let protocal = row.protocal;
  if (row.protocal == "TCP") {
    protocal = 1;
  } else if (row.protocal == "ICMP") {
    protocal = 3;
  }
  let deployParam = {
    name: row.name,
    protocal: protocal,
    remoteAddr: row.remoteAddr,
    remotePort: row.remotePort,
    id: row.id,
    enable: Number(row.enable),
  };

  req_updateNetDetectionRules(treeStore.treeDeviceId, deployParam).then((res) => {
    ElMessage({
      message: "设置成功",
      type: "success",
    });
    netDetectionTable.value.getTableData();
  });
};
const arrangeFn = async (row) => {
  netDetectionEditSubmit2(row);
};
const submitFn = () => {
  netDetectionEditSubmit(toRaw(netDetectionForm));
};
// 白名单列表日志表格 列名与数据源设置
const netDetectionTableFields = reactive([
  { name: "name", label: "名称" },
  { name: "protocal", label: "协议" },
  { name: "remoteAddr", label: "目的地址" },
  { name: "remotePort", label: "目的端口" },
  { name: "enable", label: "启用", ev: arrangeFn, type: "switch" },
]);
const handleAddNetDetection = () => {
  delete netDetectionForm.id;
  netDetectionForm.name = "";
  netDetectionForm.protocal = 1;
  netDetectionForm.remoteAddr = "";
  netDetectionForm.remotePort = "";
  netDetectionForm.enable = false;
  disableRemotePort.value = false;
  netDetectionDialogVModel.value = true;
};
const headerOperation = [{ name: "新增", ev: handleAddNetDetection, icon: Plus }];

// linux修改弹出框
const netDetectionDialogVModel = ref(false);
const netDetectionForm = reactive({
  id: "",
  name: "",
  protocal: 1,
  remoteAddr: "",
  remotePort: null,
  enable: false,
});
const editFn = (index, row) => {
  netDetectionForm.id = row.id;
  netDetectionForm.name = row.name;
  netDetectionForm.protocal = row.protocal == "ICMP" ? 3 : 1;
  netDetectionForm.remoteAddr = row.remoteAddr;
  netDetectionForm.remotePort = row.remotePort;
  netDetectionForm.enable = Boolean(row.enable);
  disableRemotePort.value = row.protocal == "ICMP" ? true : false;
  netDetectionDialogVModel.value = true;
};
const delFn = async (index, row) => {
  await req_deleteNetDetectionRules(treeStore.treeDeviceId, {
    id: row.id,
  }).then((res) => {
    ElMessage({
      message: "操作成功",
      type: "success",
    });
  });
  netDetectionTable.value.getTableData();
};
const operationCol = [
  { name: "修改", ev: editFn },
  { name: "删除", ev: delFn, popconfirm: true },
];
const getNetDetectionData = async (countParams, searchParams) => {
  if (treeStore.treeDeviceId) {
    let whitelistParams = {
      page: searchParams.$page,
      size: searchParams.$limit,
    };
    await req_getNetDetectionRules(treeStore.treeDeviceId, whitelistParams).then(
      (res) => {
        if (!res.data.status) {
          return;
        }
        let typeStr = "";
        netDetectionTableData.value = res.data.data.map((item) => {
          switch (item.protocal) {
            case 1:
              typeStr = "TCP";
              break;
            case 3:
              typeStr = "ICMP";
              break;
          }
          return {
            ...item,
            enable: Boolean(item.enable),
            protocal: typeStr,
          };
        });
        netDetectionTotal.value = Number(res.data.total) || 0;
        netDetectionTable.value.finish();
      },
      (err) => {
        netDetectionTable.value.finish();
      }
    );
  } else {
    netDetectionTableData.value = [];
  }
  netDetectionTable.value.finish();
};

onMounted(() => {
  if (!treeStore.treeDeviceId) {
    return;
  }
  req_getOutreach(treeStore.treeDeviceId, getParams).then((res) => {
    if (res.data.osType == "linux") {
      showLinux.value = true;
    } else {
      setOutreachDataObj(res.data.data[0].net_detect);
    }
  });
});
watch(
  () => treeStore.treeDeviceId,
  (newVal, oldVal) => {
    if (!treeStore.treeDeviceId) {
      return;
    }
    req_getOutreach(newVal, getParams).then((res) => {
      if (res.data.osType == "linux") {
        showLinux.value = true;
      } else {
        setOutreachDataObj(res.data.data[0].net_detect);
        initData = toRaw(JSON.parse(res.data.data[0].net_detect).intranetset);
      }
    });
  }
);
</script>

<style lang="scss" scoped>
.outreach-box {
  background-color: #fff;
  color: #555;
  padding: 10px;
  border-radius: 3px;
  box-shadow: 0px 2px 4px 0px rgba(64, 32, 224, 0.06);
  .form-seach {
    padding-left: 40px;
  }
}
.margin-auto {
  margin: 0 auto;
}
</style>
